package com.sc.es.service.house;

import com.fasterxml.jackson.databind.JsonNode;
import com.fasterxml.jackson.databind.ObjectMapper;
import com.sc.es.common.HouseResult;
import com.sc.es.common.ServiceResult;
import com.sc.es.dto.SubwayDTO;
import com.sc.es.dto.SubwayStationDTO;
import com.sc.es.dto.SupportAddressDto;
import com.sc.es.entity.SubWayStation;
import com.sc.es.entity.Subway;
import com.sc.es.entity.SupportAddress;
import com.sc.es.repo.SubWayRepo;
import com.sc.es.repo.SubWayStationRepo;
import com.sc.es.repo.SupportAddressRepository;
import com.sc.es.search.BaiduMapLocation;
import com.sc.es.service.IAddressService;
import groovy.util.logging.Slf4j;
import org.apache.http.HttpResponse;
import org.apache.http.HttpStatus;
import org.apache.http.client.HttpClient;
import org.apache.http.client.methods.HttpGet;
import org.apache.http.impl.client.HttpClients;
import org.apache.http.util.EntityUtils;
import org.modelmapper.ModelMapper;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.stereotype.Service;

import java.io.IOException;
import java.io.UnsupportedEncodingException;
import java.net.URLEncoder;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;
import java.util.Map;

/**
 * @author sc
 * Created on  2018/2/7
 */
@Service
@Slf4j
public class AddressService implements IAddressService{
    @Autowired
    private SupportAddressRepository addressRepository;
    @Autowired
    private SubWayRepo subWayRepo;
    @Autowired
    private SubWayStationRepo subWayStationRepo;
    @Autowired
    private ModelMapper modelMapper;
    @Autowired
    private ObjectMapper objectMapper;
    @Value("${baidu.key}")
    private  String BAIDU_MAP_SERVER_KEY;

    private static final String BAIDU_MAP_GEOCONV_API = "http://api.map.baidu.com/geocoder/v2/?";

    /**
     * POI数据管理接口
     */
    private static final String LBS_CREATE_API = "http://api.map.baidu.com/geodata/v3/poi/create";

    private static final String LBS_QUERY_API = "http://api.map.baidu.com/geodata/v3/poi/list?";

    private static final String LBS_UPDATE_API = "http://api.map.baidu.com/geodata/v3/poi/update";

    private static final String LBS_DELETE_API = "http://api.map.baidu.com/geodata/v3/poi/delete";

    @Override
    public ServiceResult findAllCitiesByLevel() {
        List<SupportAddress> allByLevel = addressRepository.findAllByLevel(SupportAddress.Level.CITY.getValue());
        return CommonPart(allByLevel);
    }

    @Override
    public ServiceResult findAllRegionsByCity(String city) {
        List<SupportAddress> allByLevelAndBelongTo = addressRepository.findAllByLevelAndBelongTo(SupportAddress.Level.REGION.getValue(), city);
        return CommonPart(allByLevelAndBelongTo);
    }

    @Override
    public ServiceResult findSubWay(String cityName) {
        return new ServiceResult(subWayRepo.findAllByCityEnName(cityName));
    }

    @Override
    public ServiceResult findSubWayStation(Integer subwayId) {
        return new ServiceResult(subWayStationRepo.findAllBySubwayId(subwayId));
    }

    @Override
    public Map<SupportAddress.Level, SupportAddressDto> findCityAndRegion(String cityEnName, String regionEnName) {
        Map<SupportAddress.Level, SupportAddressDto> result = new HashMap<>();

        SupportAddress city = addressRepository.findByEnNameAndLevel(cityEnName, SupportAddress.Level.CITY
                .getValue());
        SupportAddress region = addressRepository.findByEnNameAndBelongTo(regionEnName, city.getEnName());

        result.put(SupportAddress.Level.CITY, modelMapper.map(city, SupportAddressDto.class));
        result.put(SupportAddress.Level.REGION, modelMapper.map(region, SupportAddressDto.class));
        return result;
    }

    @Override
    public HouseResult<SubwayDTO> findSubWayById(Integer subwayLineId) {
        if (subwayLineId == null) {
            return HouseResult.notFound();
        }
        Subway subway = subWayRepo.findOne(subwayLineId);
        if (subway == null) {
            return HouseResult.notFound();
        }
        return HouseResult.of(modelMapper.map(subway, SubwayDTO.class));
    }

    @Override
    public HouseResult<SubwayStationDTO> findSubWayStationById(Integer subwayStationId) {
        if (subwayStationId == null) {
            return HouseResult.notFound();
        }
        SubWayStation station = subWayStationRepo.findOne(subwayStationId);
        if (station == null) {
            return HouseResult.notFound();
        }
        return HouseResult.of(modelMapper.map(station, SubwayStationDTO.class));
    }

    @Override
    public HouseResult<SupportAddressDto> findCity(String cityEnName) {
        if(cityEnName==null){
            return  HouseResult.notFound();
        }
        SupportAddress byEnNameAndLevel = addressRepository.findByEnNameAndLevel(cityEnName, SupportAddress.Level.CITY.getValue());
        if(byEnNameAndLevel==null){
            return HouseResult.notFound();
        }
        SupportAddressDto addressDto = modelMapper.map(byEnNameAndLevel, SupportAddressDto.class);
        return HouseResult.of(addressDto);
    }

    @Override
    public HouseResult<BaiduMapLocation> getBaiduMapLocation(String city, String address) {
        String encodeAddress;
        String encodeCity;
        try {
            encodeAddress= URLEncoder.encode(address,"UTF-8");
            encodeCity=URLEncoder.encode(city,"UTF-8");

        } catch (UnsupportedEncodingException e) {
            return new HouseResult<>(false,"error encoder");
        }
        HttpClient httpClient = HttpClients.createDefault();
        StringBuilder builder = new StringBuilder(BAIDU_MAP_GEOCONV_API);
        builder.append("address=").append(encodeAddress).append("&")
                .append("city=").append(city).append("&")
        .append("output=json&")
        .append("ak=").append(BAIDU_MAP_SERVER_KEY);
        HttpGet httpGet = new HttpGet(builder.toString());
        try {
            HttpResponse response = httpClient.execute(httpGet);
            if(response.getStatusLine().getStatusCode()!= HttpStatus.SC_OK){
                return new HouseResult<>(false,"can not get baidu map location");
            }
            String result = EntityUtils.toString(response.getEntity(), "UTF-8");
            JsonNode jsonNode = objectMapper.readTree(result);
            int status = jsonNode.get("status").asInt();
            if(status!=0){
                return new HouseResult<>(false,"error status"+status);
            }else {
                BaiduMapLocation baiduMapLocation = new BaiduMapLocation();
                JsonNode jsonNode1 = jsonNode.get("result").get("location");
                baiduMapLocation.setLongtitude(jsonNode1.get("lng").asDouble());
                baiduMapLocation.setLatitude(jsonNode1.get("lat").asDouble());
                return HouseResult.of(baiduMapLocation);
            }
        } catch (IOException e) {
            return new HouseResult<>(false,"error to fetch baidu api");
        }
    }

    /**
     * 封装公共的代码
     * @param list
     * @return
     */
    private ServiceResult CommonPart(List<SupportAddress> list){
        List<SupportAddressDto> dtos = new ArrayList<>();
        for (SupportAddress supportAddress : list) {
            SupportAddressDto dto = modelMapper.map(supportAddress,SupportAddressDto.class);
            dtos.add(dto);
        }
        return new ServiceResult(dtos);
    }
}
